#ifndef PIPO_H
#define PIPO_H


#include <inttypes.h>
#include <string.h>
#include <stdlib.h>

//#include <stddef.h>
//#include <avr/io.h>

//#include <avr/pgmspace.h>

#include <avr/eeprom.h>
//#include <avr/sleep.h>
//#include <avr/interrupt.h>

//#include <util/delay.h>
#include <util/atomic.h>
//#define pgm_read_adr(address_short) pgm_read_word(address_short)
//#include <avr/wdt.h>
//#include <math.h>


//F_CPU defined in makefile


#define NUMCHN_IN     8
#define NUMCHN_OUT    8    // number of output ppm channels
#define NUMCHN_EXTRA  8    // extra channels used for manipulation
#define NUMCHN_TOTAL (NUMCHN_OUT+NUMCHN_EXTRA)

#define NUM_LC        16  //number of logical conditions
#define NUM_MIXERS    32  //maximum number of mixes
#define NUM_PID       12  //maximum number of mixes

#define currEEPROMver 1


//inputs: (len is number of values - not byte length

#define IN_VAL_OFF             0  // always return 0
#define IN_VAL_ON              1  // always return 100% (RESX)
#define IN_PWM_IN_DATA         2                                      //PWM_IN data
#define IN_PWM_IN_DATA_LEN     (NUMCHN_IN)
#define IN_SENSOR_DATA         (IN_PWM_IN_DATA+IN_PWM_IN_DATA_LEN)    //raw sensor_data
#define IN_SENSOR_DATA_LEN     9
#define IN_ATTITUDE            (IN_SENSOR_DATA+IN_SENSOR_DATA_LEN)    //attitude (YPR - radians)
#define IN_ATTITUDE_LEN        3
#define IN_VELOCITY            (IN_ATTITUDE+IN_ATTITUDE_LEN)          //velocity (m/s)
#define IN_VELOCITY_LEN        3
#define IN_POSITION            (IN_VELOCITY+IN_VELOCITY_LEN)          //position (m)
#define IN_POSITION_LEN        3
#define IN_OUTPUTS             (IN_POSITION+IN_POSITION_LEN)          //output channels
#define IN_OUTPUTS_LEN         NUMCHN_TOTAL
#define IN_LOGICAL_COND        (IN_OUTPUTS+IN_OUTPUTS_LEN)            //logical conditions
#define IN_LOGICAL_COND_LEN    NUM_LC
#define IN_PID                 (IN_LOGICAL_COND+IN_LOGICAL_COND_LEN)
#define IN_PID_LEN             NUM_PID


#define LC_OFF       0
#define LC_VPOS      1  //v>offset
#define LC_VNEG      2  //v<offset
#define LC_APOS      3  //|v|>offset
#define LC_ANEG      4  //|v|<offset
#define LC_AND       5
#define LC_OR        6
#define LC_XOR       7
#define LC_EQUAL     8
#define LC_NEQUAL    9
#define LC_GREATER   10
#define LC_LESS      11
#define LC_EGREATER  12
#define LC_ELESS     13
#define LC_MAXF      13  //max function

#define LC_VOFS       0
#define LC_VBOOL      1
#define LC_VCOMP      2
#define LC_STATE(x)   ((x)<LC_AND ? LC_VOFS : ((x)<LC_EQUAL ? LC_VBOOL : LC_VCOMP))

#define MLTPX_ADD     0
#define MLTPX_SUB     1
#define MLTPX_MUL     2
#define MLTPX_DIV     3
#define MLTPX_REP     4


/*************************************************************************
 minmax on value
*************************************************************************/
#define MIN(a,b)           ( ((a)<(b)) ? (a) : (b) )
#define MAX(a,b)           ( ((a)>(b)) ? (a) : (b) )
#define MINMAX(x,min,max)  ( MIN(MAX((x),(min)),(max)) )
#define INTMINMAX(x)       ( MINMAX(x,-0x7FFF,0x7FFF)  )


typedef struct t_PIDrefVar
{
    float lastErr;
    float integral;
    int16_t val;
} __attribute__((packed)) PIDrefVar;


typedef struct t_PIDVar
{
    uint8_t   source;
    uint8_t   tgt;
    int16_t   Kp;
    int16_t   Ki;
    int16_t   Kd;
} __attribute__((packed)) PIDVar;

typedef struct t_LogicalCondition
{
    uint8_t   v1;
    uint8_t   v2;
    uint8_t   func;
} __attribute__((packed)) LogicalCondition;



typedef struct t_MixType
{
    uint8_t   dest;    // in pointer
    uint8_t   source;  // out pointer
    int16_t   scale;   // dest = (source*scale/LIN_FUNC_RES) + bias
    int16_t   bias;
    uint8_t   swtch;
    uint8_t   mltpx;
} __attribute__((packed)) MixType;



typedef struct t_LimitsType
{
    int16_t  min;  // min=-RESX -> -100%
    int16_t  max;  // max= RESX ->  100%
    int16_t  bias;
    uint8_t  inv;
} __attribute__((packed)) LimitsType;


typedef struct t_EEGeneral
{
    uint8_t   myVers;
    uint8_t   input_coding;

    //mixer variables
    MixType    mixers[NUM_MIXERS];
    LimitsType limits[NUMCHN_OUT];

    //logical conditions (cswitches)
    LogicalCondition lConditions[NUM_LC];

    //PID variables
    PIDVar pidVars[NUM_PID];

} __attribute__((packed)) EEGeneral;


extern EEGeneral gVars;  // main variable to hold all the "savable" varibles
extern float sensor_data[9];  // ax,ay,az,gx,gy,gz,mx,my,mz
//extern float sensor_data_slope[9];
extern float attitude[3];
extern uint8_t magnetometerAvailable;

extern float deltaT;


#endif // PIPO_H
